#include "gns_malloc.h"
/** 
 * @brief  获取缓存剩余空间
 * @note   
 * @param  *Buffer: 
 * @retval 空间大小
 */
uint32_t BUFFER_GetFree(BUFFER_t *Buffer)
{
	uint32_t size = 0, in, out;

	if (Buffer == NULL)
	{
		return 0;
	}
	in = Buffer->In; 
	out = Buffer->Out;
	if (in == out)
	{ 
		size = Buffer->Size;
	}
	else if (out > in)
	{ 
		size = out - in;
	}
	else
	{ 
		size = Buffer->Size - (in - out);
	}
	return size - 1; 
}
/** 
 * @brief  获取缓冲区已经占用多少空间
 * @note   
 * @param  *Buffer: 
 * @retval 
 */
uint32_t BUFFER_GetFull(BUFFER_t *Buffer)
{
	uint32_t in, out, size;

	if (Buffer == NULL)
	{ 
		return 0;
	}
	in = Buffer->In; 
	out = Buffer->Out;
	if (in == out)
	{ 
		size = 0;
	}
	else if (in > out)
	{
		size = in - out;
	}
	else
	{
		size = Buffer->Size - (out - in);
	}
	return size; 
}
/** 
 * @brief  同上
 * @note   
 * @param  *Buffer: 
 * @retval 
 */
uint32_t BUFFER_GetFullFast(BUFFER_t *Buffer)
{
	uint32_t in, out;

	if (Buffer == NULL)
	{ 
		return 0;
	}
	in = Buffer->In; 
	out = Buffer->Out;
	return (Buffer->Size + in - out) % Buffer->Size;
}
/** 
 * @brief  删除缓冲区
 * @note   
 * @param  *Buffer: 
 * @retval None
 */
void BUFFER_Reset(BUFFER_t *Buffer)
{
	if (Buffer == NULL)
	{
		return;
	}
	Buffer->In = 0;
	Buffer->Out = 0;
}
/** 
 * @brief  查找某个值是否在缓存区中
 * @note   
 * @param  *Buffer: 
 * @param  Element: 值
 * @retval 小于0未找到，大于等于0元素的下标
 */
int32_t BUFFER_FindElement(BUFFER_t *Buffer, uint8_t Element)
{
	uint32_t Num, Out, retval = 0;

	if (Buffer == NULL)
	{
		return -1;
	}

	Num = BUFFER_GetFull(Buffer);
	Out = Buffer->Out;
	while (Num > 0)
	{ 
		if (Out >= Buffer->Size)
		{
			Out = 0;
		}
		if ((uint8_t)Buffer->Buffer[Out] == (uint8_t)Element)
		{				  
			return retval; 
		}
		Out++;
		Num--;
		retval++;
	}
	return -1; 
}
/** 
 * @brief  查找多个元素在缓存的位置
 * @note   
 * @param  *Buffer: 
 * @param  *Data: 元素头指针
 * @param  Size: 长度
 * @retval 小于0未找到，大于等于0元素的下标
 */
int32_t BUFFER_Find(BUFFER_t *Buffer, const void *Data, uint32_t Size)
{
	uint32_t Num, Out, i, retval = 0;
	uint8_t found = 0;
	uint8_t *d = (uint8_t *)Data;

	if (Buffer == NULL || (Num = BUFFER_GetFull(Buffer)) < Size)
	{
		return -1;
	}
	Out = Buffer->Out; 
	while (Num > 0)
	{
		if (Out >= Buffer->Size)
		{
			Out = 0;
		}
		if ((uint8_t)Buffer->Buffer[Out] == d[0]) /* 检查buffer中的当前元素是否与数据数组中的第一个元素匹配 */
		{
			found = 1;
		}

		Out++;
		Num--;
		retval++;
		if (found)
		{		  
			i = 1; 
			while (i < Size && Num > 0)
			{ 
				if (Out >= Buffer->Size)
				{
					Out = 0;
				}
				if ((uint8_t)Buffer->Buffer[Out] != d[i])
				{
					retval += i - 1;
					break;
				}
				Out++; 
				Num--;
				i++;
			}
			if (i == Size)
			{ 
				return retval - 1;
			}
		}
	}
	return -1; 
}
/** 
 * @brief  将字符串写入缓存
 * @note   
 * @param  *Buffer: 
 * @param  *buff: 字符串
 * @retval 
 */
uint32_t BUFFER_WriteString(BUFFER_t *Buffer, const char *buff)
{
	return BUFFER_Write(Buffer, (uint8_t *)buff, strlen(buff)); 
}
/** 
 * @brief  读取字符串
 * @note   
 * @param  *Buffer: 
 * @param  *buff: 
 * @param  buffsize: 
 * @retval 
 */
uint32_t BUFFER_ReadString(BUFFER_t *Buffer, char *buff, uint32_t buffsize)
{
	uint32_t i = 0, freeMem, fullMem;
	uint8_t ch;
	if (Buffer == NULL)
	{
		return 0; 
	}

	freeMem = BUFFER_GetFree(Buffer); 
	fullMem = BUFFER_GetFull(Buffer); 
	if (							 
		fullMem == 0 ||				 
		(
			BUFFER_FindElement(Buffer, Buffer->StringDelimiter) < 0 && 
			freeMem != 0 &&											   
			fullMem < buffsize										  
			))
	{
		return 0; 
	}
	while (i < (buffsize - 1))
	{								
		BUFFER_Read(Buffer, &ch, 1);
		buff[i] = (char)ch;			
		if ((char)buff[i] == (char)Buffer->StringDelimiter)/* 检查字符串的结尾*/
		{		   
			break; 
		}
		i++; 
	}
	if (i == (buffsize - 1))
	{ 
		buff[i] = 0;
	}
	else
	{
		buff[++i] = 0;
	}
	return i; 
}

int8_t BUFFER_CheckElement(BUFFER_t *Buffer, uint32_t pos, uint8_t *element)
{
	uint32_t In, Out, i = 0;
	if (Buffer == NULL)
	{ 
		return 0;
	}

	In = Buffer->In;
	Out = Buffer->Out;
	while (i < pos && (In != Out))
	{		  
		Out++; 
		i++;
		if (Out >= Buffer->Size)
		{ 
			Out = 0;
		}
	}
	if (i == pos)
	{									
		*element = Buffer->Buffer[Out];
		return 1;						
	}
	return 0; 
}
/** 
 * @brief  缓存初始化
 * @note   
 * @param  *Buffer: 结构体指针
 * @param  Size: 长度
 * @param  *BufferPtr: 缓冲区
 * @retval 0 ok 1,error
 */
uint8_t BUFFER_Init(BUFFER_t *Buffer, uint32_t Size, void *BufferPtr)
{
	if (Buffer == NULL)
	{
		return 1;
	}
	memset(Buffer, 0, sizeof(BUFFER_t));

	Buffer->Size = Size; 
	Buffer->Buffer = BufferPtr;
	Buffer->StringDelimiter = '\n';

	if (!Buffer->Buffer)
	{																	
		Buffer->Buffer = (uint8_t *)LIB_ALLOC_FUNC(Size * sizeof(uint8_t));//申请内存
		if (!Buffer->Buffer)
		{					  
			Buffer->Size = 0; 
			return 1;		 
		}
		else
		{
			Buffer->Flags |= BUFFER_MALLOC;
		}
	}
	Buffer->Flags |= BUFFER_INITIALIZED; //初始化完成

	return 0; /* Initialized OK */
}
/** 
 * @brief  释放缓存
 * @note   
 * @param  *Buffer: 
 * @retval None
 */
void BUFFER_Free(BUFFER_t *Buffer)
{
	if (Buffer == NULL)
	{ 
		return;
	}
	if (Buffer->Flags & BUFFER_MALLOC)
	{								 
		LIB_FREE_FUNC(Buffer->Buffer);//释放内存
	}
	Buffer->Flags = 0;
	Buffer->Size = 0;
}
/** 
 * @brief  将数据写入缓存
 * @note   
 * @param  *Buffer: 缓存结构体
 * @param  *Data: 数据
 * @param  count: 数据长度 uint8_t长的
 * @retval 
 */
uint32_t BUFFER_Write(BUFFER_t *Buffer, const void *Data, uint32_t count)
{
	uint32_t i = 0;
	uint32_t free;
	const uint8_t *d = (const uint8_t *)Data;
#if BUFFER_FAST
	uint32_t tocopy;
#endif

	if (Buffer == NULL || count == 0)
	{ 
		return 0;
	}
	if (Buffer->In >= Buffer->Size)
	{ 
		Buffer->In = 0;
	}
	free = BUFFER_GetFree(Buffer); //获取剩余内存
	if (free < count)
	{ 
		if (free == 0)
		{ 
			return 0;
		}
		count = free; 
	}


#if BUFFER_FAST
	tocopy = Buffer->Size - Buffer->In; //计个数
	if (tocopy > count)
	{ 
		tocopy = count;
	}
	memcpy(&Buffer->Buffer[Buffer->In], d, tocopy);
	i += tocopy;								
	Buffer->In += tocopy;
	count -= tocopy;
	if (count > 0)
	{												
		memcpy(Buffer->Buffer, (void *)&d[i], count); 
		Buffer->In = count;							
	}
	if (Buffer->In >= Buffer->Size)
	{ /* Check input overflow */
		Buffer->In = 0;
	}
	return (i + count); /* 返回内存中的个数*/
#else
	while (count--)
	{										
		Buffer->Buffer[Buffer->In++] = *d++; 
		i++;								
		if (Buffer->In >= Buffer->Size)
		{
			Buffer->In = 0;
		}
	}
	return i;
#endif
}
/** 
 * @brief  将数据反向写入缓存顶部
 * @note   非线程安全函数
 * @param  *Buffer: 
 * @param  *Data: 数据
 * @param  count: 长度 uint8_t类型长
 * @retval 元素个数
 */
uint32_t BUFFER_WriteToTop(BUFFER_t *Buffer, const void *Data, uint32_t count)
{
	uint32_t i = 0;
	uint32_t free;
	uint8_t *d = (uint8_t *)Data;

	if (Buffer == NULL || count == 0)
	{ 
		return 0;
	}
	if (Buffer->In >= Buffer->Size)
	{ 
		Buffer->In = 0;
	}
	if (Buffer->Out >= Buffer->Size)
	{ 
		Buffer->Out = 0;
	}
	free = BUFFER_GetFree(Buffer); /* Get free memory */
	if (free < count)
	{ 
		if (free == 0)
		{ 
			return 0;
		}
		count = free; 
	}
	d += count - 1;
	while (count--)
	{ 
		if (Buffer->Out == 0)
		{
			Buffer->Out = Buffer->Size - 1;
		}
		else
		{
			Buffer->Out--;
		}
		Buffer->Buffer[Buffer->Out] = *d--; 
		i++;								
	}
	return i; 
}
/** 
 * @brief  读取数据
 * @note   
 * @param  *Buffer: 
 * @param  *Data: 外部空间的指针
 * @param  count: 长度 uint8_t类型长
 * @retval 
 */
uint32_t BUFFER_Read(BUFFER_t *Buffer, void *Data, uint32_t count)
{
	uint32_t i = 0, full;
	uint8_t *d = (uint8_t *)Data;
#if BUFFER_FAST
	uint32_t tocopy;
#endif

	if (Buffer == NULL || count == 0)
	{ 
		return 0;
	}
	if (Buffer->Out >= Buffer->Size)
	{ 
		Buffer->Out = 0;
	}
	full = BUFFER_GetFull(Buffer); 
	if (full < count)
	{ /* Check available memory */
		if (full == 0)
		{
			return 0;
		}
		count = full; 
	}
#if BUFFER_FAST
	tocopy = Buffer->Size - Buffer->Out; 
	if (tocopy > count)
	{ /* Check for copy count */
		tocopy = count;
	}
	memcpy(d, &Buffer->Buffer[Buffer->Out], tocopy);
	i += tocopy;									
	Buffer->Out += tocopy;
	count -= tocopy;
	if (count > 0)
	{										 
		memcpy(&d[i], Buffer->Buffer, count); 
		Buffer->Out = count;				 
	}
	if (Buffer->Out >= Buffer->Size)
	{ /* Check output overflow */
		Buffer->Out = 0;
	}
	return (i + count); 
#else
	while (count--)
	{										 
		*d++ = Buffer->Buffer[Buffer->Out++];
		i++;								
		if (Buffer->Out >= Buffer->Size)
		{ /* Check output overflow */
			Buffer->Out = 0;
		}
	}
	return i; 
#endif
}